package orz.mikeneck.server.locrec.controller;

import java.io.IOException;
import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import orz.mikeneck.server.locrec.exception.LocRecUserNotFoundException;
import orz.mikeneck.server.locrec.model.LocRecGpsModel;
import orz.mikeneck.server.locrec.model.LocRecGpsModelImpl;
import orz.mikeneck.server.locrec.model.LocRecUserModelImpl;
import orz.mikeneck.server.locrec.persistent.GpsRecord;
import orz.mikeneck.server.locrec.persistent.utils.PersistenceManagerUtil;
import orz.mikeneck.server.locrec.utils.DateUtils;
import orz.mikeneck.server.locrec.utils.GsonWrapper;
import orz.mikeneck.server.locrec.utils.UserServiceUtil;

import com.google.appengine.api.users.UserServiceFactory;

public class ApiGetRecord implements ApiHandler {


	private HttpServletRequest request;

	private HttpServletResponse response;

	private UserServiceUtil util;

	private Date called;

	public ApiGetRecord(){
		this.util = new UserServiceUtil(
				UserServiceFactory.getUserService());
	}

	@Override
	public ApiHandler requestIs(HttpServletRequest req) {
		this.request = req;
		return this;
	}

	@Override
	public ApiHandler responseIs(HttpServletResponse resp) {
		this.response = resp;
		return this;
	}

	@Override
	public boolean execute() {
		String timeZone = getTimeZoneString();
		try {
			String loginId = getLoginId();
			
			Date fromDate = getFromDate();
			Date toDate = getToDate();
			
			int page = getPage();
			int startRecord = getStartRecord(page);
			int endRecord = getEndRecord(page);
			
			List<GpsRecord> results = (new LocRecGpsModelImpl())
				.recordsFrom(startRecord)
				.recordsTo(endRecord)
				.addFilter(LocRecGpsModel.DEFAULT_FILTER)
				.and()
				.addFilter(LocRecGpsModel.FILTER_END_DATE)
				.and()
				.addFilter(LocRecGpsModel.FILTER_START_DATE)
				.addParameter(LocRecGpsModel.PARAM_LOGIN_ID)
				.addParameter(LocRecGpsModel.PARAM_END_DATE)
				.addParameter(LocRecGpsModel.PARAM_START_DATE)
				.findRecordsWithParams((Object)loginId,
						(Object)fromDate, (Object)toDate);
			
			GsonWrapper gson = new GsonWrapper();
			String json = gson.parse(results);
			
			response.setContentType(CONTENT_TYPE_JSON);
			response.getWriter().println(json);
			
			return true;
			
		} catch (LocRecUserNotFoundException e) {
			return false;
		} catch(NumberFormatException e) {
			return false;
		} catch (ParseException e) {
			return false;
		} catch (IOException e) {
			return false;
		}
	}

	public Date getToDate() throws ParseException {
		return getDateByParam(GetParams.TO_DATE);
	}

	public Date getFromDate() throws ParseException {
		return getDateByParam(GetParams.FROM_DATE);
	}

	public Date getDateByParam(String param) throws ParseException {
		TimeZone zone = getTimeZone();
		String strDate = request.getParameter(param);
		if(strDate == null){
			return called;
		}
		Date date = DateUtils.parseDate(strDate, zone);
		return date;
	}

	public int getStartRecord(int page) {
		int size = getPageSize();
		return size * (page - 1);
	}

	private int getPageSize() {
		int size = GetParams.DEFAULT_SIZE;
		String strSize = request.getParameter(GetParams.SIZE);
		if(strSize != null){
			try {
				int parsedSize = Integer.parseInt(strSize);
				if(parsedSize > 0)
					size = parsedSize;
			} catch (NumberFormatException e) {
			}
		}
		return size;
	}

	public int getEndRecord(int page) {
		int size = getPageSize();
		return size * page;
	}

	public int getPage() throws NumberFormatException {
		String reqPage = request.getParameter(GetParams.PAGE_NUM);
		if(reqPage == null){
			reqPage = "1";
		}else if("".equals(reqPage.trim())){
			reqPage = "1";
		}
		int page = Integer.parseInt(reqPage);
		return (page < 1)? 1 : page;
	}

	public String getTimeZoneString() {
		return DateUtils.getTimeZone(
				request.getParameter(GetParams.TIME_ZONE));
	}

	public TimeZone getTimeZone() {
		return TimeZone.getTimeZone(getTimeZoneString());
	}

	public String getLoginId() throws LocRecUserNotFoundException {
		String loginId = request.getParameter(LOGIN_ID);
		if(loginId == null){
			return new LocRecUserModelImpl()
				.persistenceManagerIs(PersistenceManagerUtil.getManager())
				.emailIs(util.getEmail())
				.createSearchQuery()
				.getLocRecUser()
				.getLoginId();
		}else{
			return loginId;
		}
	}

	@Override
	public ApiHandler calledAt(Date calledAt) {
		this.called = calledAt;
		return this;
	}
}
